package org.loong.crypto.extension.cms;

import java.util.Objects;

import org.loong.crypto.common.exception.CryptoException;
import org.loong.crypto.service.CryptoService;
import org.loong.crypto.spi.ExtensionLoader;

/**
 * The CMS provider factory.
 */
public final class CMSProviderFactory {

    public static final String GENERATE = "generate";

    public static final String PARSE = "parse";

    private CMSProviderFactory() {}

    /**
     * New instance Cryptographic Message Syntax provider.
     *
     * @param dataFormat the dataFormat
     * @return the cryptographic message syntax provider
     */
    public static CMSProvider newInstance(final String dataFormat) {
        return ExtensionLoader.getExtensionLoader(CMSProvider.class).getJoin(dataFormat);
    }

    /**
     * Match generate or parse.
     * 
     * @param cryptoService the cryptoService
     * @param params the params
     * @return return the generate or parse data if the match is successful, otherwise return null
     */
    public static byte[] match(final CryptoService cryptoService, final CMSParameters params) {
        switch (params.getWay()) {
            case GENERATE:
                return generate(cryptoService, params);
            case PARSE:
                return parse(cryptoService, params);
            default:
                return null;
        }
    }

    /**
     * Generate data.
     * 
     * @param cryptoService the cryptoService
     * @param params the params
     * @return the data
     * @throws CryptoException {@link CryptoException}
     */
    private static byte[] generate(final CryptoService cryptoService, final CMSParameters params) throws CryptoException {
        if (Objects.isNull(params.getDataFormat())) {
            throw new CryptoException("The ContentType is not specified.");
        }

        return newInstance(params.getDataFormat()).generate(cryptoService, params);
    }

    /**
     * Parse data.
     * 
     * @param cryptoService the cryptoService
     * @param params the params
     * @return the data
     * @throws CryptoException {@link CryptoException}
     */
    private static byte[] parse(final CryptoService cryptoService, final CMSParameters params) throws CryptoException {
        if (Objects.isNull(params.getDataFormat())) {
            throw new CryptoException("The ContentType is not specified.");
        }

        return newInstance(params.getDataFormat()).parse(cryptoService, params);
    }
}
